using System;
using System.Collections.Generic;
using System.Reflection;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace SBPweb.RIA.Shared.Contracts.Entities
{

    ///// <summary>
    ///// Implements basic functionallity of Entity
    ///// </summary>
    //public abstract class Entity : ExtendableBase, IEntity
    //{

    //    #region Private fields

    //    private EntityActionState mAState = EntityActionState.Detached;
    //    private EntityTransactionState mTState;

    //    ///// <summary>
    //    ///// Values of entity
    //    ///// </summary>
    //    //protected Dictionary<string, object> mValues = new Dictionary<string, object>();
		
    //    private static Dictionary<Type, List<string>> mColumns = new Dictionary<Type, List<string>>();
    //    private static Dictionary<string, ConstructorInfo> mFactoryPrototype = new Dictionary<string, ConstructorInfo>();

    //    #endregion

    //    #region Constructor logic

    //    /// <summary>
    //    /// Initializes a new Entity instance
    //    /// </summary>
    //    public Entity()
    //    {
    //    }

    //    /// <summary>
    //    /// Initializes a new Entity instance from an entity instance
    //    /// </summary>
    //    /// <param name="ancestor">Ancestor of entity</param>
    //    public Entity(Entity ancestor)
    //    {
    //        this.propertyValues = ancestor.propertyValues;
    //        this.propertyTypes = ancestor.propertyTypes;
    //        this.ActionState = ancestor.ActionState;
    //        this.TransactionState = ancestor.TransactionState;
    //    }

    //    #endregion

    //    #region Public property accessors

    //    /// <summary>
    //    /// Returns EntityActionState of entity
    //    /// </summary>
    //    [SpecialName()]
    //    public virtual EntityActionState ActionState
    //    {
    //        get
    //        {
    //            return mAState;
    //        }
    //        set
    //        {
    //            mAState = value;
    //        }
    //    }

    //    /// <summary>
    //    /// Returns EntityTransactionState of entity
    //    /// </summary>
    //    [SpecialName()]
    //    public virtual EntityTransactionState TransactionState
    //    {
    //        get
    //        {
    //            return mTState;
    //        }
    //        set
    //        {
    //            mTState = value;
    //        }
    //    }

    //    /// <summary>
    //    /// Returns Values of entity (key is the name)
    //    /// </summary>
    //    [ReadOnly(true)]
    //    [SpecialName()]
    //    public Dictionary<string, object> Values
    //    {
    //        get
    //        {
    //            return propertyValues;
    //        }
    //    }
		
    //    /// <summary>
    //    /// Returns Columns of entity (key is the type)
    //    /// </summary>
    //    [ReadOnly(true)]
    //    public static Dictionary<Type, List<string>> Columns
    //    {
    //        get
    //        {
    //            return mColumns;
    //        }
    //    }

    //    /// <summary>
    //    /// Handler for TransactionState change
    //    /// </summary>
    //    /// <param name="sender"></param>
    //    /// <param name="oldState"></param>
    //    /// <param name="newState"></param>
    //    public delegate void TransactionStateChanged(IEntity sender, EntityTransactionState oldState, EntityTransactionState newState);

    //    /// <summary>
    //    /// Fired when the TransactionState property changed
    //    /// </summary>
    //    public event TransactionStateChanged OnTransactionStateChanged;

    //    #endregion

    //    #region Static state management methods

    //    /// <summary>
    //    /// Sets the ActionState of the entity
    //    /// </summary>
    //    /// <param name="entity">IEntity entity</param>
    //    /// <param name="newState">EntityActionState newState</param>
    //    public static void SetActionState(IEntity entity, EntityActionState newState)
    //    {
    //        (entity as Entity).ActionState = newState;
    //    }

    //    /// <summary>
    //    /// Sets the TransactionState of the entity
    //    /// </summary>
    //    /// <param name="entity">IEntity entity</param>
    //    /// <param name="newState">EntityTransactionState newState</param>
    //    public static void SetTransactionState(IEntity entity, EntityTransactionState newState)
    //    {
    //        Entity e = (entity as Entity);
    //        if (e == null)
    //        {
    //            throw new ArgumentNullException("entity");
    //        }
    //        EntityTransactionState oldState = e.TransactionState;
    //        e.TransactionState = newState;
    //        if (e.OnTransactionStateChanged != null)
    //        {
    //            e.OnTransactionStateChanged.Invoke(entity, oldState, newState);
    //        }
    //        if (OnEntityTransactionStateChanged != null)
    //        {
    //            OnEntityTransactionStateChanged.Invoke(entity, oldState, newState);
    //        }
    //    }

    //    /// <summary>
    //    /// Fired when the TransactionState of an entity has changed
    //    /// </summary>
    //    public static event TransactionStateChanged OnEntityTransactionStateChanged;

    //    #endregion

    //    #region Static helper methods
        
    //    /// <summary>
    //    /// Registers the entity type public properties to columns dictionary
    //    /// </summary>
    //    /// <typeparam name="T">Entity type</typeparam>
    //    public static void RegisterEntityTypeToColumns<T>() where T : Entity
    //    {
    //        RegisterEntityTypeToColumns(typeof(T));
    //    }
		
    //    /// <summary>
    //    /// Registers the entity type public properties to columns dictionary
    //    /// </summary>
    //    /// <param name="entityType">Type entityType</param>
    //    public static void RegisterEntityTypeToColumns(Type entityType)
    //    {
    //        if (mColumns.ContainsKey(entityType))
    //        {
    //            return;
    //        }

    //        List<string> list = new List<string>();

    //        foreach (PropertyInfo pI in entityType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
    //        {
    //            if (pI.Attributes != PropertyAttributes.SpecialName && !list.Contains(pI.Name))// && !IsColumnNameAlreadyRegistered(type.UnderlyingSystemType, pI.Name))
    //            {
    //                list.Add(pI.Name);
    //            }
    //        }

    //        mColumns.Add(entityType, list);
    //    }

    //    /// <summary>
    //    /// Registers the constructor of the entity to FactoryPrototypes
    //    /// </summary>
    //    /// <typeparam name="T">Type of Entity</typeparam>
    //    /// <param name="entity">Type entity</param>
    //    public static void RegisterEntityTypeToFactory<T>(Type entity)
    //    {
    //        RegisterEntityTypeToFactory(entity, typeof(T).FullName);
    //    }

    //    /// <summary>
    //    /// Registers the constructor of the entity to FactoryPrototypes
    //    /// </summary>
    //    /// <param name="entityType">Type entityType</param>
    //    /// <param name="interfaceTypeName">string interfaceTypeName</param>
    //    public static void RegisterEntityTypeToFactory(Type entityType, string interfaceTypeName)
    //    {
    //        lock (mFactoryPrototype)
    //        {
    //            if (mFactoryPrototype.ContainsKey(interfaceTypeName))
    //            {
    //                throw new ArgumentException(string.Format("InterfaceTypeName {0} already", interfaceTypeName));
    //            }
    //            ConstructorInfo cI = entityType.GetConstructor(new Type[] { typeof(Entity) });
    //            if (cI == null)
    //            {
    //                throw new ArgumentException(string.Format("Type {0} does not have a constructor with the needed signature!", entityType));
    //            }
    //            mFactoryPrototype.Add(interfaceTypeName, cI);
    //        }
    //    }

    //    /// <summary>
    //    /// Clones an entity to type T
    //    /// </summary>
    //    /// <typeparam name="T">Type of result entity</typeparam>
    //    /// <param name="entity">entity to clone</param>
    //    /// <returns>Entity of type T</returns>
    //    public static T CreateInstanceClone<T>(Entity entity)
    //    {
    //        return CreateInstanceClone<T>(entity, typeof(T).FullName);
    //    }

    //    /// <summary>
    //    /// Clones an entity to type T
    //    /// </summary>
    //    /// <typeparam name="T">Type of result entity</typeparam>
    //    /// <param name="entity">entity to clone</param>
    //    /// <param name="interfaceTypeName">Type name of the interface of T</param>
    //    /// <returns>Entity of type T</returns>
    //    public static T CreateInstanceClone<T>(Entity entity, string interfaceTypeName)
    //    {
    //        lock (mFactoryPrototype)
    //        {
    //            if (!mFactoryPrototype.ContainsKey(interfaceTypeName))
    //            {
    //                throw new ArgumentOutOfRangeException(interfaceTypeName);
    //            }

    //            ConstructorInfo cI = mFactoryPrototype[interfaceTypeName];
    //            Entity clone = (Entity)(cI.Invoke(new object[] { entity }));

    //            return (T)(IEntity)clone;
    //        }
    //    }

    //    #endregion

    //    //#region Property accessors

    //    ///// <summary>
    //    ///// Returns the Value of a property
    //    ///// </summary>
    //    ///// <typeparam name="T">Type of property</typeparam>
    //    ///// <param name="propertyName">Name of property</param>
    //    ///// <returns>T</returns>
    //    //public virtual T GetValue<T>(string propertyName)
    //    //{
    //    //    if (!mValues.ContainsKey(propertyName))
    //    //    {
    //    //        return default(T);
    //    //    }
    //    //    return (T)mValues[propertyName];
    //    //}

    //    ///// <summary>
    //    ///// Sets the Value of a property
    //    ///// </summary>
    //    ///// <typeparam name="T">Type of property</typeparam>
    //    ///// <param name="propertyName">Name of property</param>
    //    ///// <param name="value">Value of property</param>
    //    //public virtual void SetValue<T>(string propertyName, T value)
    //    //{
    //    //    mValues[propertyName] = value;
    //    //}

    //    ///// <summary>
    //    ///// Sets the Value of a property and inserts it into the values dictionary 
    //    ///// </summary>
    //    ///// <typeparam name="T">Type of property</typeparam>
    //    ///// <param name="propertyName">Name of property</param>
    //    ///// <param name="value">Value of property</param>
    //    //public virtual void SetValueEx<T>(string propertyName, T value)
    //    //{
    //    //    if (!mValues.ContainsKey(propertyName))
    //    //    {
    //    //        mValues.Add(propertyName, value);
    //    //    }
    //    //    else
    //    //    {
    //    //        mValues[propertyName] = value;
    //    //    }
    //    //}

    //    //#endregion

    //    #region Virtual methods

    //    /// <summary>
    //    /// Creates a clone of the entity
    //    /// </summary>
    //    /// <returns></returns>
    //    public virtual object Clone()
    //    {
    //        Entity entity = (Entity)Activator.CreateInstance(this.GetType());
    //        lock(this)
    //        {
    //            foreach(KeyValuePair<string, object> kvp in this.propertyValues)
    //            {
    //                entity.propertyValues.Add(kvp.Key, kvp.Value);
    //                entity.propertyTypes.Add(kvp.Key, propertyTypes[kvp.Key]);
    //            }
    //        }
    //        return entity;
    //    }

    //    #endregion

    //    #region Private helper functions

    //    private static bool IsColumnNameAlreadyRegistered(Type type, string name)
    //    {
    //        if (Entity.Columns.ContainsKey(type))
    //        {
    //            if (Entity.Columns[type].Contains(name))
    //            {
    //                return true;
    //            }
    //        }
    //        if (Entity.Columns.ContainsKey(type.BaseType))
    //        {
    //            if (Entity.Columns[type.BaseType].Contains(name))
    //            {
    //                return true;
    //            }
    //        }
    //        return false;
    //    }

    //    #endregion

    //}

}